﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry {
    public struct Vector {
        public static Vector RIGHT   = new Vector(1.0f, 0.0f, 0.0f);
        public static Vector UP      = new Vector(0.0f, 1.0f, 0.0f);
        public static Vector FORWARD = new Vector(0.0f, 0.0f, 1.0f);

        public float x, y, z;

        public Vector(float x, float y, float z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public static explicit operator Normal(Vector v) {
            return new Normal(v.x, v.y, v.z);
        }

        public static Vector operator +(Vector u, Vector v) {
            return new Vector(u.x + v.x, u.y + v.y, u.z + v.z);
        }
        public static Vector operator -(Vector u, Vector v) {
            return new Vector(u.x - v.x, u.y - v.y, u.z - v.z);
        }
        public static Vector operator *(Vector v, float a) {
            return new Vector(a * v.x, a * v.y, a * v.z);
        }
        public static Vector operator *(float a, Vector v) {
            return v * a;
        }
        public static Vector operator /(Vector v, float a) {
            float r = 1.0f / a;
            return v * r;
        }

        public static Vector operator -(Vector v) {
            return new Vector(-v.x, -v.y, -v.z);
        }

        public static float dot(Vector u, Vector v) {
            return u.x * v.x + u.y * v.y + u.z * v.z;
        }
        // u x v = | i  j  k  |
        //         | ux uy uz |
        //         | vx vy vz |
        public static Vector cross(Vector u, Vector v) {
            return new Vector(
                u.y * v.z - v.y * u.z,
                u.z * v.x - v.z * u.x,
                u.x * v.y - v.x * u.y);
        }

        public float dot(Vector v) { return Vector.dot(this, v); }
        public float absDot(Vector v) { return Math.Abs(this.dot(v)); }
        public Vector cross(Vector v) { return Vector.cross(this, v); }

        public float square() {
            return this.x * this.x + this.y * this.y + this.z * this.z;
        }
        public float length() {
            return (float) Math.Sqrt(this.square());
        }
        public Vector normalize() { return this / this.length(); }
    }
}
